package com.dlc.apk.ui.activity

import android.os.Environment
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.dlc.hardwareprotocol.serialport.command.recv.RecvBA
import com.dlc.installerlibrary.AutoInstaller
import com.dlc.apk.R
import com.dlc.apk.api.ApiConstants
import com.dlc.apk.api.ApiManager
import com.dlc.apk.api.entity.*
import com.dlc.apk.base.BaseActivity
import com.dlc.apk.base.BaseApp
import com.dlc.apk.base.adapter.databinding.BaseBindingAdapter

import com.dlc.apk.core.MQTTClient
import com.dlc.apk.core.ShipmentTestingProgress
import com.dlc.apk.databinding.ActivityMainBinding
import com.dlc.apk.databinding.LayoutUserItemBinding
import com.dlc.apk.receiver.NetworkChangeReceiver
import com.dlc.apk.service.OnProcessListener
import com.dlc.apk.service.user.IUserService
import com.dlc.apk.service.user.impl.UserService

import com.dlc.apk.ui.fragment.*
import com.dlc.apk.ui.model.*
import com.dlc.apk.utils.*
import com.jeremyliao.liveeventbus.LiveEventBus
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.lang.StringBuilder
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

/**
 * @author We
 * @date 2020/11/13
 */
class MainActivity : BaseActivity() {
    private lateinit var appForm: AppForm
    private lateinit var appVersion: AppVersion
    private lateinit var deviceInfoModel: DeviceInfoModel
    private lateinit var userService: IUserService

    private lateinit var welcomeFragment: WelcomeFragment

    private lateinit var activityMainBinding: ActivityMainBinding

    override fun getLayoutId(): Int {
        return R.layout.activity_main
    }

    override fun initViewModels() {
        appForm = AppForm()
        deviceInfoModel = DeviceInfoModel()
        appVersion = AppVersion()

        deviceInfoModel.name.set("设备编号: ${DeviceUtil.androidId}")
    }

    override fun initServices() {
        userService = UserService()
    }

    override fun init() {
        activityMainBinding = getViewDataBinding<ActivityMainBinding>()!!
        activityMainBinding.appForm = appForm
        appForm.welcome.set(getString(R.string.app_name))
        appForm.versionName.set(DeviceUtil.packageVersion)
        activityMainBinding.testte.setOnClickListener { v ->
            appForm.welcome.set("last time:" + DateUtil.nowToString())
            appForm.isDebug.set(!appForm.isDebug.get())
        }
        activityMainBinding.tvDebug.setOnClickListener { v -> doLoadUserList() }
        activityMainBinding.usersRecyclerView.layoutManager = LinearLayoutManager(this)
        val userAdapter: BaseBindingAdapter<User, LayoutUserItemBinding> = object : BaseBindingAdapter<User, LayoutUserItemBinding>(this) {
            override fun getLayoutResId(viewType: Int): Int {
                return R.layout.layout_user_item
            }

            override fun onBindItem(binding: LayoutUserItemBinding, item: User) {
                binding.user = item
                binding.executePendingBindings()
            }
        }
        activityMainBinding.usersRecyclerView.adapter = userAdapter

        //顶部logo栏
        activityMainBinding.llTopBar.appForm = appForm
        //点击logo
        activityMainBinding.llTopBar.ivLogoIcon.setOnClickListener {

        }
        activityMainBinding.llTopBar.deviceInfoModel = deviceInfoModel

        //点击位置跳转到debug界面
        activityMainBinding.llTopBar.llLogoIcon.setOnClickListener { v -> toDebug() }

        //点击返回
        activityMainBinding.llTopBar.ivBack.setOnClickListener { v ->
            onBackPressed()
        }

        //点击日期时间 返回
        activityMainBinding.llTopBar.tvDatetime.setOnClickListener { v ->
            onBackPressed()
        }

        //点击中间title
        activityMainBinding.llTopBar.tvAppName.setOnClickListener {
            //finish()
        }

        //隐藏返回&倒计时
        activityMainBinding.llTopBar.ivBack.visibility = View.GONE
        activityMainBinding.llTopBar.tvCountDown.visibility = View.GONE
//        appForm.onProcessListener = object : OnProcessListener<Any> {
//            override fun onStart() {
//                showProgressDialog("请求登录中...")
//            }
//
//            override fun onSuccess() {
//                BaseApp.instance.runOnUiThread {
//                    //userAdapter.items.clear()
//                    userAdapter.items.addAll(appForm.users)
//                }
//            }
//
//            override fun onFailure(extra: Any?, msg: String?) {
//                showOneToast(msg)
//            }
//
//            override fun onComplete() {
//                dismissProgressDialog()
//            }
//        }

        //进入欢迎页面
        welcomeFragment = WelcomeFragment()
        loadRootFragment(R.id.fl_main_container, welcomeFragment)
        //所观察的EventBus事件
        initEventBus()
        //检查网络 注册 BroadCastReceiver
        NetworkUtil.registerReceiver(this)
        //日期时间
        activityMainBinding.llTopBar.datetime = ""
        startTimeRefresher()

        //检测网络 如果不可用则持续检查
        if (!NetworkUtil.isNetWorkAvailable(BaseApp.instance)) {
            checkNetwork()
            return
        }
        initLoadServerData()

        supportFragmentManager.addOnBackStackChangedListener {
            LogPlus.e("###onBackStatckChanged!")
        }
    }

    private fun initLoadServerData() {
        //获取设备信息
        //getDeviceInfo()
        //启动即上传本地日志到服务器
        initLogUpload()
        //检查版本更新
        getAppVersion()
    }

    private fun initEventBus() {
        //API code != CODE_SUCCESS
        LiveEventBus.get(ApiManager.API_CODE_NOT_SUCCESS, String::class.java).observe(this, {
            showOneToast(it)
        })
        //网络变化
        LiveEventBus.get(NetworkChangeReceiver.NETWORK_CHANGE_EVENT, Boolean::class.java).observe(
            this,
            {
                val networkAvailable = it
                if (!networkAvailable) {
                    showProgressDialog("当前网络不可用")
                } else {
                    dismissProgressDialog()
                    //解决广告界面在网络恢复之后不加载问题
                    LiveEventBus.get(ApiConstants.EVENT_MQTT_UPDATE_ADVERT).post("")
                }
            })

        LiveEventBus.get(ApiConstants.EVENT_DEVICE_INFO_UPDATED, String::class.java).observe(this, {
            //重新获取设备信息
            getDeviceInfo()
        })

        //MQTT 开启设备
        LiveEventBus.get(ApiConstants.EVENT_MQTT_START_SHIPMENT, OutGoodsMQTTMsg::class.java).observe(this, {
            showToast("###开启设备###")
            startCountDown(60 * 2)
            //todo 如果当前有正在进行中的任务则提示
        })
        //MQTT 重启
        LiveEventBus.get(ApiConstants.EVENT_MQTT_RESTART, String::class.java).observe(this, {
            showToast("###重启###")
        })
        //MQTT 广告更新
        LiveEventBus.get(ApiConstants.EVENT_MQTT_UPDATE_ADVERT, String::class.java).observe(this, {
            showToast("###更新广告###")
        })
        //设备有任务进行中不可再操作
        LiveEventBus.get(ApiConstants.EVENT_TASK_RUNNING_DEVICE_BUSY, String::class.java).observe(this, {
            showToast("###设备忙碌中###")
        })
        //app版本更新
        LiveEventBus.get(ApiConstants.EVENT_MQTT_UPDATE_VERSION, UpdateVersionMQTTMsg::class.java).observe(this, {
            showToast("###app版本更新###")
            checkVersionThenDownloadAndInstall(it.version, it.downloadUrl)
        })
    }

    private val delayToCheckNetwork: Runnable = Runnable {
        checkNetwork()
    }

    private fun checkNetwork() {
        showProgressDialog("请检查网络")
        if (NetworkUtil.isNetWorkAvailable(BaseApp.instance)) {
            dismissProgressDialog()
            initLoadServerData()
            return
        }
        BaseApp.instance.uiHandler?.removeCallbacks(delayToCheckNetwork)
        BaseApp.instance.uiHandler?.postDelayed(delayToCheckNetwork, 1000 * 2)
    }

    private fun doLoadUserList() {
        appForm.users.clear()
        userService.loadUsers(appForm)
    }

    private fun getDeviceInfo() {
        deviceInfoModel.deviceNo.set("机柜编号:" + DeviceUtil.androidId)
        deviceInfoModel.onProcessListener = object : OnProcessListener<Any> {
            override fun onStart() {
            }

            override fun onSuccess() {
                //todo 设置照明时间段
                val deviceInfo = CacheHelper.getDeviceInfo()
            }

            override fun onFailure(extra: Any?, msg: String?) {
                showToast(msg)
            }

            override fun onComplete() {
            }
        }
        userService.getDeviceInfo(deviceInfoModel)
    }

    /**
     * 检查app版本更新
     */
    private fun getAppVersion() {
        appVersion.onProcessListener = object : OnProcessListener<Any> {
            override fun onStart() {
            }

            override fun onSuccess() {
                LogPlus.e("###app版本升级")
                if (appVersion.appVersionResponseData == null) {
                    return
                }
                checkVersionThenDownloadAndInstall(appVersion.appVersionResponseData!!.version, appVersion.appVersionResponseData!!.url)
            }

            override fun onFailure(extra: Any?, msg: String?) {
                LogPlus.e("###app版本更新检查失败,异常->$msg")
            }

            override fun onComplete() {

            }
        }
        userService.getAppVersion(appVersion)
    }

    private fun checkVersionThenDownloadAndInstall(version: String? = "", downloadUrl: String? = "") {
        if (DeviceUtil.packageVersion == version) {
            LogPlus.e("###当前已是最新版本")
            showToast("当前已是最新版本")
            return
        }
        showProgressDialog("更新文件开始下载")
        LogPlus.e("###apk开始下载更新...")
        val cacheFileDir = Environment.getExternalStorageDirectory().absolutePath + File.separator + "Download"
        val autoInstaller = AutoInstaller.Builder(BaseApp.instance).setMode(AutoInstaller.MODE.ROOT_ONLY).setCacheDirectory(cacheFileDir).build()
        if (TextUtils.isEmpty(downloadUrl)) {
            LogPlus.e("###文件url.length = 0")
            return
        }
        autoInstaller.installFromUrl(ApiConstants.getFullUrl(downloadUrl!!), object : AutoInstaller.OnUpdateResultListener {
            override fun onSuccess() {

            }

            override fun onFailed(th: Throwable?, msg: String?) {
                BaseApp.instance.runOnUiThread {
                    showToast("失败->异常:${th?.message} $msg")
                }
            }

            override fun onDownloadProgress(totalSize: Long, currentSize: Long) {
                BaseApp.instance.runOnUiThread {
                    val progress = (currentSize * 1.0f / totalSize * 100).toInt()
                    showProgressDialog("更新文件下载中 $progress")
                }
                LogPlus.e("###下载进度->totalSize:$totalSize,currentSize:$currentSize")
            }
        })
    }

    fun showLogoBar() {
        appForm.isShowLogoBar.set(true)
    }

    fun hideLogoBar() {
        //appForm.isShowLogoBar.set(false)
    }

    override fun onBackPressed() {
        val canBack = fragmentBackStackCount > 0
        if (canBack) {
            super.onBackPressed()
        }
        if (canBack && isCanShowLogo()) {
            showLogoBar()
        } else {
            hideLogoBar()
        }
        //super.onBackPressed();
    }

    private fun isCanShowLogo(): Boolean {
        var canShow = true
        val noAutoBackToWelcomeFragmentClasses = arrayOf(
            WelcomeFragment::class.java,
        )
        for (fragmentClazz in noAutoBackToWelcomeFragmentClasses) {
            if (backFragment?.javaClass == fragmentClazz || backFragment == null) {
                canShow = false
                break
            }
        }
        return canShow
    }

    fun backToWelcome() {
        hideLogoBar()
        popAll()
    }

    fun logout() {
        hideLogoBar()
        popAll()
    }

    private fun toDebug() {

    }

    override fun onDestroy() {
        super.onDestroy()
        //取消网络BroadCastReceiver
        NetworkUtil.unregisterReceiver(this)
        startTimeRefresherDisposable?.dispose()
    }

    private fun initLogUpload() {
        //上传本地日志到服务器
        MQTTClient.uploadLog()
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        startCountDown(60 * 2)
        return super.dispatchTouchEvent(ev)
    }

    private var countDownDisposable: Disposable? = null
    private fun startCountDown(count: Long) {
        //LogPlus.e("###开始倒计时###count->$count")
        countDownDisposable?.dispose()
        countDownDisposable = Observable.interval(0, 1, TimeUnit.SECONDS)
            .take(count)
            .map { c -> count - c }
            .subscribeOn(Schedulers.computation())
            .doOnSubscribe { } //执行计时任务前
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { c ->
                //LogPlus.e("###倒计时->$c")
                //排除某些不需要倒计时的界面
                val canBackToWelcome = isCanBackToWelcome()
                activityMainBinding.llTopBar.tvCountDown.text = if (canBackToWelcome) "${c.toInt()}s" else ""
                if (c.toInt() == 1) {
                    LogPlus.e("###倒计时结束")
                    //排除某些不需要倒计时的界面
                    //val canBackToWelcome = isCanBackToWelcome()
                    if (canBackToWelcome) {
                        backToWelcome()
                    }
                }
            }
    }

    private fun isCanBackToWelcome(): Boolean {
        var canBackToWelcome = true
        val noAutoBackToWelcomeFragmentClasses = arrayOf(
            WelcomeFragment::class.java,
            TestingFragment::class.java,
        )
        for (fragmentClazz in noAutoBackToWelcomeFragmentClasses) {
            if (topFragment?.javaClass == fragmentClazz) {
                canBackToWelcome = false
                break
            }
        }
        return canBackToWelcome
    }

    fun showTestingFragment(force: Boolean) {
        if (isInBackStack(TestingFragment::class.java)) {
            if (!force) {
                return
            }
            popAll()
        }
        addFragment(R.id.fl_main_container, TestingFragment())
        startCountDown(60 * 2)
    }

    fun showLoginFragment(force: Boolean) {
        if (isInBackStack(LoginFragment::class.java)) {
            if (!force) {
                return
            }
            popAll()
        }
        addFragment(R.id.fl_main_container, LoginFragment())
        startCountDown(60 * 2)
    }

    private var startTimeRefresherDisposable: Disposable? = null
    private fun startTimeRefresher() {
        startTimeRefresherDisposable?.dispose()
        startTimeRefresherDisposable = Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { aLong ->
                val nowDate = Date()
                val nowDateTimeStr = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(nowDate)
                val calendar = Calendar.getInstance()
                val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
                val dayOfWeekStrs = "日一二三四五六"
                val dayOfWeekStr = "星期${dayOfWeekStrs[dayOfWeek - 1]}"
                //日期时间
                activityMainBinding.llTopBar.datetime = "$nowDateTimeStr $dayOfWeekStr"
            }
    }
}